home *** CD-ROM | disk | FTP | other *** search
- #include <stdio.h>
- #include <stddef.h>
- #include <stdlib.h>
- #include <string.h>
- #include <tos.h>
- #include <time.h>
- #include "lancemem.h"
- #include "lancedrv.h"
- #include "pktqueue.h"
- #include "pktdrv.h"
- #include "cookie.h"
- #include "inetcust.h"
-
- #define noDEBUG
- #define noDEBUGINTR
- #define DEBUGPKT
- #define noDEBUGFREECNT
-
-
- int retval;
- int term = 0;
-
- #define TIMEOUTCNT 10000 /* count down for lance to come up */
-
- short new_stack[ISTACKSIZE/2]; /* interrupt stack */
- char *old_stack; /* must be immediately behind new_stack */
- void ( *ihandler )(void) = NULL; /* pointer to interrupt handler */
- long old_pterm;
- long lnc_vector = LANCEIVEC * sizeof(char *);
-
- int lnc_reset(void); /* reset lance, init datastructures */
- void lnc_intr(void); /* interrupt handler */
- void memcopy(register char *,register char *,register int); /* own memcopy routine */
- void (* old_berr)(); /* old bus error handler */
- extern void berr_catch(void); /* bus error handler for ST/STE */
- extern void berr_tt_catch(void); /* bus error handler for TT */
- int memok;
-
-
- volatile TMD *tmd_sent; /* last sent packet */
- PKTBUF *pkt_ring[RECVBUFFS]; /* pointers to packets waiting for recv */
- int pkt_recv; /* index of buufer receiving next packet */
- PKTPOOL *p_free; /* queue of free packets */
- u_short freecnt; /* number of free packets */
- volatile int pkt_sent = 0; /* flag if pkt is successfully sent */
- HADDR my_haddr; /* my hardware address */
-
- procref ext_tab[8] = /* subfunction table */
- {
- net_reset,
- net_open,
- net_release,
- net_send,
- net_getadr,
- net_info,
- (procref)net_pktalloc,
- net_pktfree
- };
-
- PROTOCOL protos[MAXPROTOCOLS]; /* protocols to serve */
- int protocols = 0; /* number of active protocols */
-
- et_stat stat; /* statistics block */
-
- long net_resets(void);
-
- int read_inf(void)
- {
- COOKIE *cookie;
-
- cookie = get_cookie(INETCUSTCOOKIE);
- if(!cookie || !cookie->val) return(0);
- memcopy(my_haddr,((INETCUST *)(cookie->val))->haddr,(int)sizeof(HADDR));
- return(1);
- }
-
-
-
-
- int net_info(int len, char *buf)
- {
- if(!buf) return(0);
- if(buf == (char *)1L)
- {
- lnc_reset();
- return(0);
- }
- stat.st_free = freecnt;
- memcopy(buf,(char *)&stat,(size_t)len<sizeof(stat)?len:(int)sizeof(stat));
- return(len);
- }
-
-
- int net_open(int type, int (*handler)(int,char *))
- {
- int i,new;
-
- if(!handler) return(EPARAM);
- if(protocols >= MAXPROTOCOLS) return(EPROTAVAIL);
- new = -1;
- #ifdef RESET_ON_OPEN
- if(!protocols)
- {
- net_resets();
- if(ihandler == NULL) return(EINIT);
- }
- #endif
- for(i=0; i<MAXPROTOCOLS; i++)
- { /* protocol already used */
- if(protos[i].type == type) return(EPROTUSED);
- if(protos[i].type == ET_UNUSED && new<0 ) new = i; /* find first free entry */
- }
- if(new<0) new = protocols;
- protocols++;
- protos[new].handler = handler;
- protos[new].recvd = 0;
- protos[new].sent = 0;
- protos[new].type = type;
- return(new);
- }
-
-
- int net_release(int type)
- {
- int i;
- if(!protocols) return(EPROTUSED);
- if(type == ET_UNUSED) return(EPROTUSED);
- for(i=0; i<MAXPROTOCOLS; i++)
- if(protos[i].type == type) break;
- if(i==MAXPROTOCOLS) return(EPROTUSED);
- protocols--;
- if(!protocols)
- {
- *RCP_RAP = CSR0;
- *RCP_RDP = CSR0_STOP;
- ihandler = NULL;
- }
- protos[i].type = ET_UNUSED;
- protos[i].handler = NULL;
- return(protocols);
- }
-
-
- int net_send(int len, char *buf)
- {
- register int *rdp;
- register TMD *tmd;
- register long timeout;
-
- if(!buf || !len || (buf < (char *)PPKT) || (buf > (char *)PPOOL)) return(EPARAM);
- rdp = RCP_RDP;
- pkt_sent = 0;
- if(len < 60) len = 60;
- if(len > (int)sizeof(PACKET)) return(EPKTLEN);
- *(rdp+1) = CSR0;
- if(!(*rdp & CSR0_TXON)) return(EINIT);
- tmd = (TMD *)tmd_sent;
- if((tmd->tmd1 & OWN) == OWN_CHIP) return(EINIT);
- tmd->ladr = (u_short)(buf); /* point to packet to send */
- tmd->tmd2 = -len;
- tmd->tmd3 = 0;
- tmd->tmd1 = (STP | ENP | OWN_CHIP); /* start/end of packet */
- timeout = clock() + 3*TIMEOUT;
- while(!pkt_sent && !tmd->tmd3 && clock() < timeout); /* wait till packet sent */
- if(clock() > timeout) return(ETIMEOUT);
- if(tmd->tmd3 || pkt_sent < 0) return(ECOLLISION);
- return(len);
- }
-
-
- int net_getadr(int len, char *buf)
- {
- register LNCMEM *mem;
-
- if(len>=(int)sizeof(HADDR))
- {
- mem = (LNCMEM *)RCP_MEMBOT;
- buf[0] = mem->init.haddr[1];
- buf[1] = mem->init.haddr[0];
-
- buf[2] = mem->init.haddr[3];
- buf[3] = mem->init.haddr[2];
-
- buf[4] = mem->init.haddr[5];
- buf[5] = mem->init.haddr[4];
- return((int)sizeof(HADDR));
- }
- return(0);
- }
-
-
- long net_resets(void)
- {
- int i;
- for(i=0;i<MAXPROTOCOLS;i++) /* init protocol table */
- {
- protos[i].type = ET_UNUSED;
- protos[i].handler = NULL;
- protos[i].recvd = 0;
- protos[i].sent = 0;
- }
- protocols = 0;
- p_free = p_init(MAXPKT,PPOOL,PPKT); /* init free packets */
- freecnt = MAXPKT;
- for(i=0; i< RECVBUFFS; i++)
- {
- pkt_ring[i] = ap_getpkt(ET_FREE,p_free); /* retrieve packet for receive */
- if(!pkt_ring[i]) return(EINIT);
- freecnt--;
- }
- return(lnc_reset());
- }
-
- int net_reset(void)
- {
- Supexec(net_resets);
- if( !ihandler)
- return(EINIT);
- else
- return(0);
- }
-
-
- PKTBUF *net_pktalloc(protocol)
- u_short protocol;
- {
- register PKTBUF *pkt;
- if(!p_free) net_reset();
- if(freecnt <= 1) return(NULL);
- pkt = ap_getpkt(protocol,p_free);
- if(pkt)
- freecnt--;
- return(pkt);
- }
-
-
- int net_pktfree(p_pkt)
- PKTBUF *p_pkt;
- {
- if(!p_free || !p_pkt || (p_pkt < PPKT) || (p_pkt > (PKTBUF *)PPOOL))
- {
- #ifdef DEBUGPKT
- Cconws("Packet out of band\r\n");
- #endif
- return(FALSE);
- }
- if(((long)p_pkt - (long)PPKT) % sizeof(PKTBUF))
- {
- #ifdef DEBUGPKT
- Cconws("Packet misaligned\r\n");
- #endif
- return(FALSE);
- }
- if(ap_putpkt(p_free,p_pkt))
- {
- freecnt++;
- return(TRUE);
- }
- return(FALSE);
- }
-
- /*******************************************************************/
- /*******************************************************************/
-
- #ifdef DEBUG
- char str[40];
- #endif
-
-
- void lnc_intr(void)
- {
- register int csr0;
- register int type;
- register int i;
-
- register int *rdp;
- register et_stat *et_stat;
- register TMD *md;
- register PKTBUF *pkt;
-
- rdp = RCP_RDP; /* register data port */
- *(rdp+1) = CSR0;
- csr0 = *rdp;
- if(!(csr0 & CSR0_INTR)) return;
- et_stat = &stat;
- #ifdef DEBUGINTR
- if(protocols>0)
- {
- strcpy(str,"pkt intr: ");
- itoa(csr0,str+strlen(str),16);
- strcat(str,"\r\n");
- Cconws(str);
- }
- #endif
-
- et_stat->st_err = csr0;
- et_stat->st_intr++;
- if(csr0 & CSR0_IDON)
- *(rdp) = CSR0_IDON;
- else if(csr0 & CSR0_RINT)
- {
- do
- {
- (RMD *)md = &PRMD[pkt_recv];
- *rdp = CSR0_RINT;
- if(!(((RMD *)md)->rmd1 & ERR)) /* packet ok */
- {
- /* pkt = pkt_ring[pkt_recv]; */
- pkt = (PKTBUF *)((long)RCP_MEMBOT+(((RMD *)md)->ladr));
- type = pkt->et_type;
- et_stat->st_received++;
- if(protocols > 0)
- {
- #ifdef DEBUG
- itoa(type,str,16);
- Cconws(str);
- Cconws(" from ");
- ltoa((long)pkt,str,16);
- Cconws(str);
- Cconws("\r\n");
- #endif
- for(i=0;i<MAXPROTOCOLS; i++)
- {
- if(protos[i].type == type && freecnt > 0)
- { /* must have one packet free */
- if(protos[i].handler &&
- protos[i].handler(((RMD *)md)->mcnt,(char *)pkt))
- {
- /* retrieve one packet for receive */
- pkt_ring[pkt_recv] = ap_getpkt(ET_FREE,p_free);
- freecnt--;
- /* set new receive packet */
- ((RMD *)md)->ladr = (u_short)(pkt_ring[pkt_recv]);
- et_stat->st_got++;
- protos[i].recvd++;
- }
- break;
- }
- }
- }
- }
- else
- {
- if(((RMD *)md)->rmd1 & CRC)
- et_stat->st_crc++;
- lnc_reset();
- return;
- }
- ((RMD *)md)->mcnt = 0; /* free packet */
- ((RMD *)md)->rmd1 = OWN_CHIP; /* give packet back to lance */
- pkt_recv++;
- if(pkt_recv >= RECVBUFFS) pkt_recv = 0;
- } while((PRMD[pkt_recv].rmd1 & OWN) == OWN_HOST);
- }
- else if(csr0 & CSR0_TINT)
- {
- md = (TMD *)tmd_sent;
- if((md->tmd1 & OWN) == OWN_HOST) /* packet given back to host */
- {
- if((md->tmd1) & ERR)
- {
- pkt_sent = -1;
- et_stat->st_xmiterr++;
- }
- else
- {
- pkt_sent = 1;
- et_stat->st_sent++;
- if(md->tmd1 & (MORE | ONE | DEF))
- et_stat->st_collision++;
- }
- }
- else
- et_stat->st_xmiterr++;
- *rdp = CSR0_TINT; /* clear interrupt bit */
- }
- else if(csr0 & CSR0_ERR)
- {
- et_stat->st_missed++;
- *(rdp+1) = 0;
- *rdp = CSR0_CERR | CSR0_MERR | CSR0_BABL | CSR0_MISS;
- }
- *(rdp+1) = CSR0;
- *rdp = CSR0_INEA;
- }
-
-
- int lnc_reset(void)
- {
- register LNCMEM *mem;
- register TMD *md;
- register u_long i;
- register int *rdp;
-
- rdp = RCP_RDP;
- *(rdp+1) = CSR0;
- *rdp = CSR0_STOP;
- /* init data structures */
-
- mem = (LNCMEM *)RCP_MEMBOT;
- mem->init.mode = 0; /* mode word */
-
- mem->init.haddr[5] = my_haddr[4];
- mem->init.haddr[4] = my_haddr[5];
- mem->init.haddr[3] = my_haddr[2];
- mem->init.haddr[2] = my_haddr[3];
- mem->init.haddr[1] = my_haddr[0];
- mem->init.haddr[0] = my_haddr[1];
-
- mem->init.laf[0] = 0; /* logical adress filter */
- mem->init.laf[1] = 0; /* logical adress filter */
-
- mem->init.rdrp.drp_lo = (u_short)offsetof(LNCMEM,rmd[0]);
- /* ((u_long)&(PRMD[0])); */ /* receive ring descr. pointer */
- mem->init.rdrp.drp_hi = 0;
- mem->init.rdrp.len = RECVRLEN;
-
- mem->init.tdrp.drp_lo = (u_short)offsetof(LNCMEM,tmd);
- /* ((u_long)&PTMD); */ /* transmit ring descr. pointer */
- mem->init.tdrp.drp_hi = 0;
- mem->init.tdrp.len = XMITRLEN;
-
- md = &mem->tmd;
- md->ladr = 0; /* dont know adress of packet to send */
- md->tmd1 = OWN_HOST;
- md->tmd2 = 0; /* zero pkt size */
- md->tmd3 = 0;
- for(i=0; i< RECVBUFFS; i++)
- {
- (RMD *)md = mem->rmd+i;
- ((RMD *)md)->ladr = (u_short)((char *)pkt_ring[i]);
- ((RMD *)md)->rmd1 = OWN_CHIP;
- ((RMD *)md)->rmd2 = -MAXPKTLEN; /* 2's complement (maximum size) */
- ((RMD *)md)->mcnt = 0;
- }
- tmd_sent = &mem->tmd;
- pkt_recv = 0;
- *(rdp+1) = CSR3;
- *rdp = CSR3_BSWP;
- *(rdp+1) = CSR2;
- *rdp = 0;
- *(rdp+1) = CSR1;
- *rdp = 0;
- *(rdp+1) = CSR0;
- *rdp = CSR0_STRT | CSR0_INIT;
- i = TIMEOUTCNT * 100;
- do
- {
- if(*rdp & CSR0_IDON) break;
- }while(--i > 0);
- if(i<=0 || (*rdp & CSR0_ERR))
- {
- *rdp = CSR0_STOP;
- ihandler = NULL;
- return(EINIT);
- }
- ihandler = lnc_intr;
- *rdp = CSR0_IDON; /* clear idon-bit */
- *rdp = CSR0_INEA; /* enable interrupts */
- return(0);
- }
-
- main()
- {
- COOKIE *cookie;
- void (*call)(void);
-
- Cconws("\r\nPacket driver V1.1 for RieblCard Plus ");
- cookie = get_cookie(PKTCOOKIE);
- if(cookie)
- {
- (long)call = ((long *)cookie->val)[NETRESET];
- call(); /* reset network */
- Cconws("\r\nexisting driver reset\r\n");
- return(0);
- }
- memok = 0;
- old_berr = Setexc(2,(void (*)())(-1));
- cookie = get_cookie(MACHINECOOKIE);
- if(!cookie || ((cookie->val >> 16) != 2))
- Setexc(2,berr_catch);
- else
- Setexc(2,berr_tt_catch);
- *RCP_MEMBOT=0xaa;
- Setexc(2,old_berr);
- if(memok)
- {
- Cconws("\r\nEthernet Card NOT found\r\n\a");
- return(0);
- }
- if(!read_inf())
- {
- Cconws("INETCUST not installed !!\r\n");
- }
- else
- {
- #ifdef DEBUGFREECNT
- Cconws("freecnt at 0x");
- Cconws(ltoa((long)&freecnt,(char *)new_stack,16));
- Cconws("\r\n\a\a");
- #endif
- ihandler = NULL;
- Supexec(lnc_install);
- if(net_reset() < 0)
- {
- Setexc(LANCEIVEC, (void (*)())old_intr);
- Cconws("Cannot init Ethernet Card\r\n\a");
- return(0);
- }
- add_cookie(PKTCOOKIE,(long)ext_tab);
- Cconws("installed\r\n(c) hw,pm fortec 1991,1992\r\n");
- Ptermres(_PgmSize,0);
- }
- return(0);
- }